package com.example.onlinemonitoring.comCenter;

import com.example.onlinemonitoring.Util.CRC16;
import com.example.onlinemonitoring.Util.CommPortManager;
import com.example.onlinemonitoring.Util.HexUtil;
import com.example.onlinemonitoring.autoRun.ComRunner;
import com.example.onlinemonitoring.model.Tgsensor;
import com.example.onlinemonitoring.model.Tghistory;
import com.example.onlinemonitoring.model.Appdevice;
import com.example.onlinemonitoring.serviceImpl.TgsensorServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.context.annotation.Scope;

import java.net.SocketException;
import java.text.ParseException;
import java.util.Date;
import java.util.Random;
import java.util.List;
import java.util.ArrayList;

/*
套管
*/
@Service("tgCom")
@Scope("prototype")
public class TgCom extends CommPortManager {
    @Autowired
    private TgsensorServiceImpl tgsensorServiceImpl;

    @Override
    public void receiveData(String str) {
        try {
            str = str.toUpperCase();
            setText(str);
            // 条件判断自己写
            String addrstr = str.substring(8, 12);
            Integer addr = parseHex4(addrstr);

            if (!"A6".equals(str.substring(6, 8)))
                return;
            reSend[addrindex] = 0;
            addrindex++;
            Integer startIndex = 12;// 数据起始位置
            Random ran = new Random();
            if (str.length() > 16) {
                float LastAWcurrent = 0, LastBWcurrent = 0, LastCWcurrent = 0;
                setText("设备返回数据： 站点号：" + ad.getStationid() + " 设备地址：" + addr);
                byte[] mybyte_Awcurrnet = HexUtil.hexString2Bytes(str.substring(20, 28));
                LastAWcurrent = HexUtil.byte2float(mybyte_Awcurrnet) * 10;
                byte[] mybyte_Bwcurrnet = HexUtil.hexString2Bytes(str.substring(28, 36));
                LastBWcurrent = HexUtil.byte2float(mybyte_Bwcurrnet) * 10;
                byte[] mybyte_Cwcurrnet = HexUtil.hexString2Bytes(str.substring(36, 44));
                LastCWcurrent = HexUtil.byte2float(mybyte_Cwcurrnet) * 10;
                // byte[] mybyte_Awcurrnet = HexUtil.hexString2Bytes(str.substring(12, 20));
                // LastAWcurrent = HexUtil.byte2float(mybyte_Awcurrnet);
                // byte[] mybyte_Bwcurrnet = HexUtil.hexString2Bytes(str.substring(20, 28));
                // LastBWcurrent = HexUtil.byte2float(mybyte_Bwcurrnet);
                // byte[] mybyte_Cwcurrnet = HexUtil.hexString2Bytes(str.substring(28, 36));
                // LastCWcurrent = HexUtil.byte2float(mybyte_Cwcurrnet);
                float lastandeltaA = (float) (ran.nextFloat() * (0.12 - 0.08) + 0.08);
                float lastandeltaB = (float) (ran.nextFloat() * (0.12 - 0.08) + 0.08);
                float lastandeltaC = (float) (ran.nextFloat() * (0.12 - 0.08) + 0.08);
                if(LastAWcurrent<0.2)
                lastandeltaA=0;
                if(LastBWcurrent<0.2)
                lastandeltaB=0;
                if(LastCWcurrent<0.2)
                lastandeltaC=0;
                //LastAWcurrent = 20;
                // float lastadischargeamount = (float) (ran.nextFloat() * LastAWcurrent );               
                // float lastbdischargeamount = (float) (ran.nextFloat() * LastBWcurrent );
                // float lastcdischargeamount = (float) (ran.nextFloat() * LastCWcurrent );

                Tgsensor tgsensor = new Tgsensor();
                // 设置设备地址
                tgsensor.setStationid(ad.getStationid());
                tgsensor.setDevicegroup(ad.getDevicegroup());
                tgsensor.setDeviceaddr(addr);

                // 查询对象
                Tgsensor record = tgsensorServiceImpl.getModel(tgsensor);
                if (record == null) {
                    setText("当前数据库无监测点：设备地址" + addr);
                }
                String stlyestr = record.getStyle();
                if ((stlyestr == null) || (stlyestr.equals(""))) {
                    stlyestr = "awcurrent|1|A相泄漏电流,bwcurrent|1|B相泄漏电流,cwcurrent|1|C相泄漏电流,tandeltaa|1|A相介损,tandeltab|1|B相介损,tandeltac|1|C相介损";
                    record.setStyle(stlyestr);
                }

                float Currentbegin=0,Currentend=0;
                float Pdbegin=0,Pdend=0;
                Currentbegin = isnull(record.getCurrentbegin());
                Currentend = isnull(record.getCurrentend());
                if(Currentend==0)
                Currentend=1;
                Pdbegin = isnull(record.getPdbegin());
                Pdend = isnull(record.getPdend());

                float pdbl = (float) (Pdend-Pdbegin)/(Currentend-Currentbegin);
                float AWcurrenttmp =LastAWcurrent,BWcurrenttmp =LastBWcurrent,CWcurrenttmp =LastCWcurrent;
                if(LastAWcurrent<Currentbegin) 
                AWcurrenttmp = Currentbegin;
                if(LastAWcurrent>Currentend) 
                AWcurrenttmp = Currentend;
                if(LastBWcurrent<Currentbegin) 
                BWcurrenttmp = Currentbegin;
                if(LastBWcurrent>Currentend) 
                BWcurrenttmp = Currentend;
                if(LastCWcurrent<Currentbegin) 
                CWcurrenttmp = Currentbegin;
                if(LastCWcurrent>Currentend) 
                CWcurrenttmp = Currentend;

                float lastadischargeamount = AWcurrenttmp*pdbl * ran.nextFloat();
                float lastbdischargeamount = BWcurrenttmp*pdbl * ran.nextFloat();
                float lastcdischargeamount = CWcurrenttmp*pdbl * ran.nextFloat();
                if(lastadischargeamount<Pdbegin)
                lastadischargeamount = Pdbegin;
                if(lastadischargeamount>Pdend) 
                lastadischargeamount = Pdend;
                if(lastbdischargeamount<Pdbegin)
                lastbdischargeamount = Pdbegin;
                if(lastbdischargeamount>Pdend) 
                lastbdischargeamount = Pdend;
                if(lastcdischargeamount<Pdbegin)
                lastcdischargeamount = Pdbegin;
                if(lastcdischargeamount>Pdend) 
                lastcdischargeamount = Pdend;

                setText("A相泄漏电流：" + LastAWcurrent + "mA" + " B相泄漏电流：" + LastBWcurrent + "mA" + " C相泄漏电流："
                        + LastCWcurrent + "mA");
                setText("A相介损：" + lastandeltaA + "%"+ " B相介损：" + lastandeltaB + "%"+ " C相介损：" + lastandeltaC+ "%");
                setText("A相放电量：" + lastadischargeamount + "pC"+ " B相放电量："+ lastbdischargeamount + "pC" +" C相放电量：" + lastcdischargeamount+ "pC");

                record.setLastawcurrent(LastAWcurrent);
                record.setLastbwcurrent(LastBWcurrent);
                record.setLastcwcurrent(LastCWcurrent);
                record.setLasttandeltaa(lastandeltaA);
                record.setLasttandeltab(lastandeltaB);
                record.setLasttandeltac(lastandeltaC);
                record.setLastadischargeamount(lastadischargeamount);
                record.setLastbdischargeamount(lastbdischargeamount);
                record.setLastcdischargeamount(lastcdischargeamount);
                AddAndUpdate(record);
            } else {
                setText("从设备返回的数据有误！请检查串口！");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            setText("从设备返回的数据有误！请检查串口！");
        }
    }

    private void read61850(String str) {
        Tgsensor currrecord = new Tgsensor();
        currrecord.setStationid(ad.getStationid());
        currrecord.setDevicegroup(ad.getDevicegroup());
        List<Tgsensor> lastrecordlist = tgsensorServiceImpl.getLists(currrecord);
        if (lastrecordlist.size() != 0) {
            if (lastrecordlist.get(0).getStyle61850() != null) {
                String[] style = lastrecordlist.get(0).getStyle61850().split(",");
                for (String s : style) {
                    map61850.put(s.split("\\|")[0], s.split("\\|")[1]);
                }
            }
        }
        for (Tgsensor lastrecord : lastrecordlist) {
            currrecord.setDeviceaddr(lastrecord.getDeviceaddr());
            String alm = "";
            try {
                currrecord.setLastawcurrent(read61850FloatValue(
                        String.format(isnull(map61850.get("LeakAA")), lastrecord.getDeviceaddr())));
                currrecord.setLastawcurrent(read61850FloatValue(
                        String.format(isnull(map61850.get("LeakAB")), lastrecord.getDeviceaddr())));
                currrecord.setLastawcurrent(read61850FloatValue(
                        String.format(isnull(map61850.get("LeakAC")), lastrecord.getDeviceaddr())));
                currrecord.setLasttandeltaa(read61850FloatValue(
                        String.format(isnull(map61850.get("DieLossA")), lastrecord.getDeviceaddr())));
                currrecord.setLasttandeltab(read61850FloatValue(
                        String.format(isnull(map61850.get("DieLossB")), lastrecord.getDeviceaddr())));
                currrecord.setLasttandeltac(read61850FloatValue(
                        String.format(isnull(map61850.get("DieLossC")), lastrecord.getDeviceaddr())));
                alm += read61850IntValue(
                        String.format(isnull(map61850.get("SupDevRun1")), lastrecord.getDeviceaddr())) == 1
                                ? "套管A相泄漏电流告警,"
                                : "";
                alm += read61850IntValue(
                        String.format(isnull(map61850.get("SupDevRun2")), lastrecord.getDeviceaddr())) == 1
                                ? "套管B相泄漏电流告警,"
                                : "";
                alm += read61850IntValue(
                        String.format(isnull(map61850.get("SupDevRun3")), lastrecord.getDeviceaddr())) == 1
                                ? "套管C相泄漏电流告警,"
                                : "";
                currrecord.setLastcommunicationstatus(read61850IntValue(
                        String.format(isnull(map61850.get("MoDevConf1")), lastrecord.getDeviceaddr())));
            } catch (SocketException e) {
                if (Close()) {
                    tgsensorServiceImpl.UpdateStatus(ad, 1);
                    ComRunner.netmap.remove(ad.getId());
                }
            } catch (Exception e) {
                setText("读取数据出错！" + e.toString());
            }

            if (alm.equals("")) {
                currrecord.setLastalarmlevel(0);
                currrecord.setLastalarmmessage(alm);
                GetNormalAlarm("套管" + lastrecord.getDeviceaddr(), lastrecord.getDevicegroup(),
                        lastrecord.getDeviceaddr(), 0,
                        lastrecord.getPointname(), "", false);
                setText("套管");
            } else {
                currrecord.setLastalarmlevel(2);
                currrecord.setLastalarmmessage(alm);
                GetNormalAlarm("套管" + lastrecord.getDeviceaddr(), lastrecord.getDevicegroup(),
                        lastrecord.getDeviceaddr(), 0,
                        lastrecord.getPointname(), alm, true);
                setText(alm);
            }

            currrecord.setLastdatatime(new Date());
            currrecord.setLasthisdatatime(addHistory(lastrecord));
            tgsensorServiceImpl.Update(currrecord, false);
            StringBuilder str2 = new StringBuilder();
            str2.append("套管设备返回数据： 站点号：1 地址" + currrecord.getDeviceaddr());
            str2.append("A相泄漏电流：" + currrecord.getLastawcurrent());
            str2.append("B相泄漏电流：" + currrecord.getLastbwcurrent());
            str2.append("C相泄漏电流：" + currrecord.getLastcwcurrent());
            str2.append("A相介损：" + currrecord.getLasttandeltaa());
            str2.append("B相介损：" + currrecord.getLasttandeltab());
            str2.append("C相介损：" + currrecord.getLasttandeltac());
            setText(str2.toString());
        }
    }

    @Transactional
    private void AddAndUpdate(Tgsensor record) {
        int alarmLevel = 0;// 报警等级
        String alarmMessage = "";// 报警消息
        // 获取数据库中的报警值相关
        if (record.getWcurrentalarmvalue() == null ||
                record.getWcurrentalarmrelievevalue() == null ||
                record.getWcurrentwarnvalue() == null ||
                record.getWcurrentwarnrelievevalue() == null ||
                record.getTandeltaalarmvalue() == null ||
                record.getTandeltaalarmrelievevalue() == null ||
                record.getTandeltawarnvalue() == null ||
                record.getTandeltawarnrelievevalue() == null||
                record.getPdalarmvalue() == null ||
                record.getPdalarmrelievevalue() == null ||
                record.getPdwarnvalue() == null ||
                record.getPdwarnrelievevalue() == null) {
            setText("设备地址" + record.getDeviceaddr() + " 未设置报警值！");
            return;
        }
        List<Integer> array = new ArrayList<>();
        record.setLastawalarmstatus(
                GetAlarmStatus(isnull(record.getLastawcurrent()), isnull(record.getWcurrentalarmvalue()),
                        isnull(record.getWcurrentalarmrelievevalue()), isnull(record.getWcurrentwarnvalue()),
                        isnull(record.getWcurrentwarnrelievevalue()),
                        isnull(record.getLastawalarmstatus()), true, "A相泄漏电流", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastawalarmstatus(), "A相泄漏电流");
        array.add(record.getLastawalarmstatus());
        record.setLastbwalarmstatus(
                GetAlarmStatus(isnull(record.getLastbwcurrent()), isnull(record.getWcurrentalarmvalue()),
                        isnull(record.getWcurrentalarmrelievevalue()), isnull(record.getWcurrentwarnvalue()),
                        isnull(record.getWcurrentwarnrelievevalue()),
                        isnull(record.getLastbwalarmstatus()), true, "B相泄漏电流", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastbwalarmstatus(), "B相泄漏电流");
        array.add(record.getLastbwalarmstatus());
        record.setLastcwalarmstatus(
                GetAlarmStatus(isnull(record.getLastcwcurrent()), isnull(record.getWcurrentalarmvalue()),
                        isnull(record.getWcurrentalarmrelievevalue()), isnull(record.getWcurrentwarnvalue()),
                        isnull(record.getWcurrentwarnrelievevalue()),
                        isnull(record.getLastcwalarmstatus()), true, "C相泄漏电流", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastcwalarmstatus(), "C相泄漏电流");
        array.add(record.getLastcwalarmstatus());
        record.setLastatdalarmstatus(
                GetAlarmStatus(isnull(record.getLasttandeltaa()), isnull(record.getTandeltaalarmvalue()),
                        isnull(record.getTandeltaalarmrelievevalue()), isnull(record.getTandeltawarnvalue()),
                        isnull(record.getTandeltawarnrelievevalue()),
                        isnull(record.getLastatdalarmstatus()), true, "A相介损", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastatdalarmstatus(), "A相介损");
        array.add(record.getLastatdalarmstatus());
        record.setLastbtdalarmstatus(
                GetAlarmStatus(isnull(record.getLasttandeltab()), isnull(record.getTandeltaalarmvalue()),
                        isnull(record.getTandeltaalarmrelievevalue()), isnull(record.getTandeltawarnvalue()),
                        isnull(record.getTandeltawarnrelievevalue()),
                        isnull(record.getLastbtdalarmstatus()), true, "B相介损", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastbtdalarmstatus(), "B相介损");
        array.add(record.getLastbtdalarmstatus());
        record.setLastctdalarmstatus(
                GetAlarmStatus(isnull(record.getLasttandeltac()), isnull(record.getTandeltaalarmvalue()),
                        isnull(record.getTandeltaalarmrelievevalue()), isnull(record.getTandeltawarnvalue()),
                        isnull(record.getTandeltawarnrelievevalue()),
                        isnull(record.getLastctdalarmstatus()), true, "C相介损", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastctdalarmstatus(), "C相介损");
        record.setLastapdalarmstatus(
                GetAlarmStatus(isnull(record.getLastadischargeamount()), isnull(record.getPdalarmvalue()),
                        isnull(record.getPdalarmrelievevalue()), isnull(record.getPdwarnvalue()),
                        isnull(record.getPdwarnrelievevalue()),
                        isnull(record.getLastapdalarmstatus()), true, "A相放电量", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastapdalarmstatus(), "A相放电量");
        array.add(record.getLastapdalarmstatus());
        record.setLastbpdalarmstatus(
                GetAlarmStatus(isnull(record.getLastbdischargeamount()), isnull(record.getPdalarmvalue()),
                        isnull(record.getPdalarmrelievevalue()), isnull(record.getPdwarnvalue()),
                        isnull(record.getPdwarnrelievevalue()),
                        isnull(record.getLastbpdalarmstatus()), true, "B相放电量", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastbpdalarmstatus(), "B相放电量");
        array.add(record.getLastbpdalarmstatus());
        record.setLastcpdalarmstatus(
                GetAlarmStatus(isnull(record.getLastcdischargeamount()), isnull(record.getPdalarmvalue()),
                        isnull(record.getPdalarmrelievevalue()), isnull(record.getPdwarnvalue()),
                        isnull(record.getPdwarnrelievevalue()),
                        isnull(record.getLastcpdalarmstatus()), true, "C相放电量", record.getDevicegroup(),
                        record.getDeviceaddr(),
                        record.getPointname()));
        alarmMessage += GetAlarmMessage(record.getLastcpdalarmstatus(), "C相放电量");
        array.add(record.getLastcpdalarmstatus());
        alarmLevel = HexUtil.MAX(array);
        record.setLastalarmlevel(alarmLevel);
        record.setLastalarmmessage(alarmMessage);
        record.setLastcommunicationstatus(0);
        record.setLastdatatime(new Date());
        record.setLasthisdatatime(addHistory(record));
        // record.setLasthisdatatime(addHistory(tgsensorServiceImpl.getModel(record)));
        if (tgsensorServiceImpl.Update(record, false) == 0) {
            setText("更新实时数据失败，请检查数据库连接");
        }
    }

    private Date addHistory(Tgsensor sensor) {
        if (sensor != null) {
            if (sensor.getLasthisdatatime() == null) {
                add(sensor);
                return new Date();
            } else {
                long lasttime = 0;
                long nowtime = 0;
                try {
                    lasttime = HexUtil.todate(sensor.getLasthisdatatime()).getTime();
                    nowtime = HexUtil.todate(new Date()).getTime();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                int timersp = 60000;
                if (sensor.getLastalarmlevel() != 0) {
                    timersp = ad.getHisalarmtimersp() * 1000;
                } else {
                    timersp = ad.getHistimersp() * 1000;
                }
                if (lasttime + timersp < nowtime) {
                    add(sensor);
                    return new Date();
                }
            }
        }
        return null;
    }

    private void add(Tgsensor sensor) {
        Tghistory his = new Tghistory();
        his.setDeviceaddr(sensor.getDeviceaddr());
        his.setDevicegroup(sensor.getDevicegroup());
        his.setAlarmlevel(sensor.getLastalarmlevel());
        his.setAlarmmessage(sensor.getLastalarmmessage());
        his.setDatatime(sensor.getLastdatatime());
        his.setPointname(sensor.getPointname());
        his.setStationid(sensor.getStationid());
        his.setCommunicationstatus(sensor.getLastcommunicationstatus());
        // 需要添加自己定义的属性
        his.setAwcurrent(sensor.getLastawcurrent());
        his.setBwcurrent(sensor.getLastbwcurrent());
        his.setCwcurrent(sensor.getLastcwcurrent());
        his.setTandeltaa(sensor.getLasttandeltaa());
        his.setTandeltab(sensor.getLasttandeltab());
        his.setTandeltac(sensor.getLasttandeltac());
        his.setAdischargeamount(sensor.getLastadischargeamount());
        his.setBdischargeamount(sensor.getLastbdischargeamount());
        his.setCdischargeamount(sensor.getLastcdischargeamount());
        tgsensorServiceImpl.Add(his);
    }

    @Async("threadPool")
    public void startSendThread(Appdevice Appdevice) throws Exception {

        checkType = "crc16";
        issend.put(Thread.currentThread().getId(), true);
        String cstr = "";
        String cmdtype = "";
        String nametype = "";
        int timersp = (int) Math.round(Appdevice.getTimersp() * 1000);
        while (issend.get(Thread.currentThread().getId()) != null) {
            if (isrun) {
                if ((addrindex + 8000) > Appdevice.getAddrmax() || (addrindex + 8000) < Appdevice.getAddrmin()) {
                    if (Appdevice.getAddrmin() < 8000 || Appdevice.getAddrmax() < 8000) {
                        setText("套管地址错误，地址必须大于8000");
                        Thread.sleep(timersp);
                        continue;
                    }
                    addrindex = Appdevice.getAddrmin() - 8000;
                }

                cstr = String.format(Appdevice.getCmd(), String.format("%04X", addrindex + 8000));
                cstr = cstr + CRC16.calcCrc16(cstr);
                try {
                    Send(cstr);
                } catch (Exception EX) {
                    setText(EX.toString());
                }
                reSend[addrindex]++;
                if (reSend[addrindex] > 3) {
                    tgsensorServiceImpl.UpdateStatus(ad, addrindex + 8000, 1);
                    reSend[addrindex] = 0;
                    addrindex++;
                }
            } else if (rescode != 0) {
                setText(resmsg[rescode]);
            }
            Thread.sleep(timersp);
        }
    }

}
